<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018/5/14 0014
 * Time: 下午 3:35
 */

namespace App\Common;

use App\Utility\DBTools;
use App\Enum\SysEnum;
use App\Utility\RedisTools;
use App\Utility\BaseEnum;

/**
 * 统计公共函数
 * @author XCH
 *
 */
class SumComm
{
    protected static $table_user = 'qc_user';
    protected static $table_tongji = 'qc_user_tongji';  //统计最小的计算日期
    protected static $table_fields = ['uid','userName','recUid','createDate','group_id','allBetScore','userCellScore','user_ident'];  //统计最小的计算日期
    protected static $count_min_day = 30;               //统计最小的计算日期
    protected static $count_min_winscore = 100000;       //每条代理线配置整条线的代理盈利额(money)
    protected static $count_min_windottd = 0.05;         //每条代理线盈利比基数
    
    
    //TODO 统计表字段
    public static function TABName(){
        
        return self::$table_tongji;
    }
    
    //TODO 统计一条线路的操作
    public static function sumOneLine() {
        
    }
    
    //TODO 统计字段
    public static function TABFields(){
        
        return self::$table_fields;
    }
    
    //TODO 本月统计时间(一段时间，或任意一天)
    public static function formatMonthTime(){
        //本月时间段
        return [
            'start' => date('Y-m-01'),
            'finish'=> date('Y-m-t')
        ];
    }
    
    //TODO 所有一级代理ID值
    public static function FirstAgentIds($isFull = FALSE){
        $gwhere = [
            'recUid'=> ['text' => 10000,"mark"=> '='],
            'group_id'=> ['text' => 2,"mark"=> '=']
        ];
        $agentIds = DBTools::PoolGet(self::$table_user,null,"uid,name,group_id,recUid",$gwhere);
        if ($isFull !== TRUE) {
            $agentIds = array_column($agentIds,"name","uid");
        }
        return $agentIds ?? FALSE;
    }
    
    //TODO 计算本月今天要达到的千分比值
    protected static function getTodayIKS($nowStamp = FALSE){
        /*  if(!$nowStamp){
            $nowStamp = BaseEnum::getNowTime(FALSE);
        }
        $today_index = date('d',$nowStamp);
        $lastmonth_index = date('t',$nowStamp); */
        $lastIdot = self::$count_min_windottd * 100;
        return $lastIdot;
    }
    
    
    /**
     * TODO 统计百分点数；增长率之类的数据
     * @param int $allCellTotols 本月玩家总下注分
     * @param int $allProfitScore 本月玩家总盈利
     * @param int $beforeScore 本月玩家上次统计总盈利
     * TOO 代理的盈利    ＝ 所有玩家盈利总和 (即所有代理下玩家的盈利数据) 
     */
    public static function countPofitTongji($agentId,$allCellTotols = 0,$allProfitScore = 0,$todayScore=0, $beforeScore = 0) {
        
        $baseWinDottod = self::$count_min_windottd;
        
        $platIsWins = ($allProfitScore >= 0) ? FALSE : TRUE ;       //TODO 平台是否盈利
        $winTotal = ($allCellTotols > 0) ? $allCellTotols : self::$count_min_winscore; //下注总量
        
        $allYLmoney =  abs($allProfitScore);
        $agentProfitTotal = floatval($allProfitScore);              //TODO 代理总盈亏(玩家赢的＝代理)
        
        //TODO 整体盈利比
        $countWinFoo = bcadd($allYLmoney/$winTotal, 0.00001 , 5);   //TODO计算当前百分比 
        if($platIsWins === TRUE){
            $countWinFoo = (floatval($countWinFoo) != 0) ? $countWinFoo * -1: 0;   
        }
        
        
        //TODO 相对基准点的差距
        $totalTadot = bcsub($countWinFoo,$baseWinDottod,5);   //TODO计算当前百分比 
        
        //TODO 相对于今天上次来说是增长了多少(还是负数)
        $addFee = bcsub($allProfitScore, $beforeScore , 2) ;   
        $beForeFoo = abs($addFee)/$winTotal;        //相对上次的增长百分比 
        $beForeFoo = ($addFee < 0) ? bcmul($beForeFoo , -1 , 5) : bcmul($beForeFoo , 1 , 5);
        $todayWinFoo = bcadd($todayScore/$winTotal, 0.00001 , 5);   //TODO计算当前百分比 
        
        //TODO 计算总盈利点；代理下的人员要为负数
        BaseEnum::Logger("计算百分点：本月(下注：{$winTotal},代理总盈亏：{$allProfitScore}，盈利基准点： [ {$baseWinDottod} ]  整体实际占比：{$countWinFoo}-相差：{$totalTadot}) , 今天(代理盈亏：{$todayScore} ,{$beforeScore}, 增长比：{$todayWinFoo}),代理线ID:" . $agentId,"user-login");
        
        //计算波动范围为10个点；
        $lastRes = [
            "allAgentCellScore" =>$winTotal,            //代理总下注量
            "allAgentProfit"=>  $agentProfitTotal ,     //代理总盈利额
            "totalAgentDottod"=>  floatval($countWinFoo) ,        //代理盈利占比( 只对当前的比进行计算 )
            "totalAgentAddScore"=>floatval($addFee),    //相对于上次盈利差额
            "todayScore"=>floatval($todayScore),        //今天盈亏额
            "todayDottod"=>floatval($todayWinFoo),      //今天盈亏额
            "totalMilsDottod"=>floatval($totalTadot),   //整体盈亏差距
            "totalAddDottod"=>floatval($beForeFoo),     //整体的增长幅度(增长速度)
            "setAgentWinDottod"=> $baseWinDottod
        ];
        return $lastRes;
    }
    
    /**
     * TODO 代理当天的数据处理
     * @return boolean
     */
    public static function sumALLAgentLineData($agtIds = FALSE){
        if (!$agtIds) {
            $agtIds = self::FirstAgentIds(FALSE);
        }
        if (!$agtIds) return FALSE;
        $onetjkey = SysEnum::AGENT_TONGJI_KEY;
        $toddaykey = SysEnum::AGENT_TONGJI_TODAY_KEY ;      //统计今天的数据
        $curmonthkey = SysEnum::AGENT_TONGJI_MONTH_KEY;     //统计本月的数据
        foreach ($agtIds as $agentId => $agentName){
            //TODO 历史数据缓存
            $oneHistKey = $onetjkey.$agentId;
            
            $lastVals = FALSE ;//TODO 获取最后一次的统计数据
            $allData = RedisTools::Pool_hAllKeys($oneHistKey);
            $lastIndex = !empty($allData) ? max($allData) : 0;  //最后一次也是最大值
            if ($lastIndex > 0) {
                $lastValue = RedisTools::Pool_hGet($oneHistKey, $lastIndex);
                $lastVals = !empty($lastValue) ? json_decode($lastValue,TRUE) : FALSE; 
            }
            //TODO 历史值
            $lsr1 = $lastVals["allBetScore"] ?? 0;
            $lsr2 = $lastVals["allAgentCellScore"] ?? 0;
            $lsr3 = $lastVals["allAgentProfit"] ?? 0;
            
            $nowStamp = BaseEnum::getNowTime(FALSE);
            $dataLine = self::sumOneAgentLineData($agentId,TRUE);                               //今天的整合数据
            $dataMonth = self::sumOneAgentLineData($agentId,FALSE,self::formatMonthTime());     //本月的整合数据
            $currentDayProfit = $dataLine['profitScore'] ?? 0.0 ;   //当天盈利
            $currentProfit = $dataMonth['profitScore'] ?? 0.0 ;     //当前月盈利
            $allCellTotols = $dataMonth['cellScore'] ?? 0.0 ;       //本月总下注（总量以月为单位）
            
            
            //TODO 计算代理线盈利增长比率(计算盈利比可控范围内)
            $countData = self::countPofitTongji($agentId,floatval($allCellTotols),floatval($currentProfit),floatval($currentDayProfit),floatval($lsr3));
            //TODO 当天的盈利数据
            $dataOne = [
                "agentId" => $agentId,
                "agentName"=>$agentName,
                "allBetScore" => isset($dataLine['betScore']) ? floatval($dataLine['betScore']) : 0.0,
                "allCellScore" => isset($dataLine['cellScore']) ? floatval($dataLine['cellScore']) : 0.0,
                "allWinScore" => isset($dataLine['winScore']) ? floatval($dataLine['winScore']) : 0.0,
                "allProfitScore" => $currentDayProfit,
                "allPlatProfit" => $currentDayProfit * -1 ,                 //平台(今天)赢亏分
                "todayScore" => $countData['todayScore'] ?? 0,              //平台相对于上次的赢利
                "todayDottod" => $countData['todayDottod'] ?? 0,            //平台相对于上次的增长比
                "totalAgentDottod" => $countData['totalAgentDottod'] ?? 0,  //平台整体占比
                "lastTime" => $nowStamp
            ];
            //TODO 本月的盈利数据
            $tempArr = ["agentId" => $agentId, "agentName"=>$agentName,"allBetScore" => isset($dataMonth['betScore']) ? floatval($dataMonth['betScore']) : 0.0,"lastTime" => $nowStamp];
            $dataTwo = array_merge($tempArr,$countData);
            
            //TODO 总代理线的数据统计状况
            // $lists[$toddaykey][$agentId] = json_encode($dataOne);
            //TODO 变化值不为0时才更新；$lastVals 是否更新
            $isBi1 = (floatval($dataTwo["allBetScore"]) - floatval($lsr1) <> 0) ? TRUE :FALSE ; 
            $isBi2 = (floatval($dataTwo["allAgentCellScore"]) - floatval($lsr2) <> 0) ? TRUE :FALSE ;
            $isBi3 = (floatval($dataTwo["allAgentProfit"]) - floatval($lsr3) <> 0) ? TRUE :FALSE ;
            if ($isBi1 === TRUE || $isBi2 === TRUE || $isBi3 === TRUE || empty($lastVals)) {
                RedisTools::Pool_hSet($toddaykey,   $agentId, json_encode($dataOne)); //今天的
                RedisTools::Pool_hSet($curmonthkey, $agentId, json_encode($dataTwo)); //本月的
                RedisTools::Pool_hSet($oneHistKey, $nowStamp, json_encode($dataTwo)); //本月的数据
            }
        }
        BaseEnum::Logger('执行所有代理线统计成功：AgentIds => '.json_encode($agtIds) ,'user-login');
        return TRUE;
    }
    
    //TODO 代理线统计 (每五分钟)
    public static function sumOneAgentLineData($agentId,$today = TRUE,$timeStamp = FALSE){
        $tabName = self::$table_tongji ;
        $todayChar = date('Y-m-d'); //当天值
        $fields = 'recUid,SUM(allBetScore) AS betScore, SUM(userCellScore) AS cellScore, SUM(profitScore) AS profitScore,SUM(winScore) AS winScore';
        $groupFields = ''; //'GROUP BY recUid,allBetScore,userCellScore,profitScore,winScore'; 
        //TODO 单条代理线今天的数据
        $whereOptions = "recUid IN (SELECT uid FROM qc_user WHERE group_id = 2 AND (FIND_IN_SET(?,ancestor_ids) OR uid = ?)) AND user_ident=? ";
        
        //TODO 统计时间；
        if ($today === TRUE){  //为当天或者固定一天
            $today_char = (!empty($timeStamp) && is_string($timeStamp)) ? $timeStamp : $todayChar;
            $whereOptions .= "AND createDate = '{$today_char}'" ;
        }else{
            $firstchar = $timeStamp["start"] ?? $todayChar; 
            $secondchar = $timeStamp["finish"] ?? $todayChar;
            $whereOptions .= "AND createDate BETWEEN '{$firstchar}' AND '{$secondchar}'" ;
        }
        
        //TODO 组装SQL 查询
        $querysql = "SELECT {$fields} FROM {$tabName} WHERE {$whereOptions} {$groupFields} LIMIT 1";  //查询结果
        $oneRes = DBTools::querySQL($querysql,[$agentId,$agentId,1]);                   //sql执行
        $oneRes = !empty($oneRes) ? reset($oneRes) : FALSE;
        $recIID = $oneRes["recUid"] ?? 0;
        if(!empty($oneRes) && $recIID >0 ){
            return $oneRes;
        }
        return FALSE;
    }
    
    
    //TODO 单个代理下边单个字段数据统计
    public static function sumOneAgentLineFields($agentId, $param = FALSE, $sumField = 'allBetScore') {
        $fieldStr = "recUid,COUNT(1) as totalNum,SUM({$sumField}) AS totalScore";
        $whereOpts = [
            'recUid'=> ['text' => $agentId,"mark"=> '='],
            'user_ident'=> ['text' => 1,"mark"=> '='],
        ];
        
        //统计时间处理
        $result = DBTools::PoolGetOne(self::TABName(),$fieldStr,$whereOpts);
        
        //查询结果
        if (!empty($result) && isset($result['recUid']) && intval($result['recUid']) == $agentId) {
            return $result;
        }
        return FALSE;
    }
    
    
    /**
     * TODO 获取玩家代理线的盈利状态
     * @param array $param
     */
    public static function getOneAgentWins($userId,$ro = FALSE) {
        $lastRes = [];
        //先找代理线ID
        $user_redkey = SysEnum::USER_LOGIN_REDIS_KEY.$userId;
        $loginUser = RedisTools::Pool_get($user_redkey);
        $loginUser = !empty($loginUser) ? json_decode($loginUser,TRUE):FALSE;
        if(!$loginUser){
            $loginUser = DBTools::PoolGetOne('qc_user',['uid','ancestor_ids'],["uid"=>$userId]);
        }
        $loginAnceIds = (isset($loginUser['ancestor_ids']) && !empty($loginUser['ancestor_ids'])) ? explode(',', $loginUser['ancestor_ids']) :FALSE;
        
        //代理有效
        $firstAgId = $loginAnceIds[1] ?? 0;
        $gailuv = 0 ;
        $firstWinStatus = FALSE;
        $others = "";
        if (!empty($loginAnceIds) && sizeof($loginAnceIds) >= 2 && intval($firstAgId) > 0) {
            //查询代理线的内容[QPGAME:TongJiAgents:10001]
            $tongji_redkey = SysEnum::AGENT_TONGJI_KEY.$firstAgId ;                                                         //当天列表数据
            $alltimes = RedisTools::Pool_hAllKeys($tongji_redkey);
            $maxTime = !empty($alltimes) ? max($alltimes) : FALSE;
            $lastLineValue = $maxTime ? RedisTools::Pool_hGet($tongji_redkey,$maxTime) : FALSE;
            $lastArray = !empty($lastLineValue) ? json_decode($lastLineValue , TRUE): FALSE;                                //最后一次统计数据
            BaseEnum::Logger("TODO ---JSON 解析结果:" .json_encode($lastArray));
            if(!empty($lastArray) && isset($lastArray['agentId']) && intval($lastArray['agentId']) == $firstAgId){
                $platTotalDottod = isset($lastArray['totalAgentDottod']) ? $lastArray['totalAgentDottod'] * 100 : 0;         //代理盈利统计占比
                $platNupDottod = isset($lastArray['totalMilsDottod']) ? $lastArray['totalMilsDottod'] * 100 : 0;               //上一次占比操作
                
                //TODO 处理字段处理(0.0024835)*1000  千分之几
                $yinAdd = self::getTodayIKS(FALSE);
                $others = "plat={$platTotalDottod},add={$platNupDottod},ygdot={$yinAdd}";
                
                $gailuv = 10; 
                //必杀和必不杀 
                if (floatval($platTotalDottod) >= 30) {             //代理亏损时要及时收紧
                    $firstWinStatus = TRUE; //必须杀
                }
                else if (floatval($platTotalDottod) <= -30) {             //代理亏太多时要不杀
                    $firstWinStatus = FALSE; //必须杀
                    $gailuv = 100;  
                }else{
                    $firstWinStatus = FALSE;
                    //控制增长速度($platNupDottod  上一次回收点值： 控制增长点在 10 个点之内 )
                    if (abs($platNupDottod) > 10 && $platNupDottod > 0) {
                        
                        $firstWinStatus = TRUE;          //及时杀号
                        
                    }else if (abs($platNupDottod) > 10 && $platNupDottod < 0) {
                        $gailuv = 100;                   //100不杀号；提高概率为 50%
                    }else{
                        $gailuv = 10;                    //默认都是10%的概率   
                    }
                }
            }
            $lastRes = ["agentId"=> $firstAgId, "killed"=> $firstWinStatus,"kill_dotteds" => $gailuv,"others"=> $others,'max_time_key'=>$maxTime ];
        }
        return $lastRes ?? FALSE;
    }
}